#pragma once
#include "DataStructure/Input/Constraint/SPCData.h"
#include "DataStructure/Input/Element/CBARData.h"
#include "DataStructure/Input/Load/FORCEData.h"
#include "DataStructure/Input/Node/NodeData.h"
#include "DataStructure/Input/Solver/Subcase.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/Database/DatabaseFactory.h"
#include "DBManager/IService/Input/Constraint/ISPCService.h"
#include "DBManager/IService/Input/Element/IElementService.h"
#include "DBManager/IService/Input/Load/IFORCEService.h"
#include "DBManager/IService/Input/Load/IMOMENTService.h"
#include "DBManager/IService/Input/Node/INodeService.h"
#include "DBManager/IService/Input/Subcase/ISubcaseService.h"

using namespace SG::DataStructure::FEM;
using namespace SG::DBManager;
extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;

inline void inputOneBeamMesh (DBServiceFactorySP dbServiceFactory)
{
    // 往数据库写入节点数据
    NodeData node;
    node.m_defCoord  = 0;
    node.m_dispCoord = 0;
    node.m_id        = 1;
    node.m_x[0]      = 0.0;
    node.m_x[1]      = 0.0;
    node.m_x[2]      = 0.0;
    dbServiceFactory->get<INodeService> ()->Add (node);
    node.m_id   = 2;
    node.m_x[0] = 1.0;
    node.m_x[1] = 0.0;
    node.m_x[2] = 0.0;
    dbServiceFactory->get<INodeService> ()->Add (node);
    // 定向节点
    node.m_id   = 1001;
    node.m_x[0] = 0.0;
    node.m_x[1] = 0.0;
    node.m_x[2] = 1.0;
    dbServiceFactory->get<INodeService> ()->Add (node);

    // 往数据库写入梁单元数据
    CBARData beam;
    beam.m_pId  = 1;
    beam.m_g[0] = 1;
    beam.m_g[1] = 2;
    dbServiceFactory->get<IElementService> ()->Add (beam);
}

// 无约束模型
class OneBeamNoConstrain
{
  public:
    OneBeamNoConstrain ()
    {
        DB_SERVICEFACTORY->ClearDatabase ();
        inputOneBeamMesh (DB_SERVICEFACTORY);
    }

    /// @brief 获得模型数据
    /// @return 执行模型数据的一个数据管理指针
    DBServiceFactorySP GetModel () const
    {
        return DB_SERVICEFACTORY;
    }
};

// Cantilever
class OneBeamCantilever
{
  public:
    OneBeamCantilever ()
    {
        DB_SERVICEFACTORY->ClearDatabase ();
        inputOneBeamMesh (DB_SERVICEFACTORY);
        // 1号节点固支
        SG::DataStructure::FEM::SPCData spc;
        spc.m_sId = 1;
        spc.m_g   = 1;
        spc.m_c   = 123456;
        spc.m_d   = 0;
        // 施加约束
        DB_SERVICEFACTORY->get<ISPCService> ()->Add (spc);

        // 载荷集1， 端部集中力
        {
            SG::DataStructure::FEM::FORCEData force;
            force.m_coordSysmId = 0;
            force.m_nodeId      = 2;
            force.m_load[2]     = 1000.0;
            force.m_factor      = 0.32;
            force.m_sId         = 1;
            DB_SERVICEFACTORY->get<IFORCEService> ()->Add (force);
        }

        // 载荷集2， 端部集中弯矩
        {
            SG::DataStructure::FEM::FORCEData force;
            force.m_coordSysmId = 0;
            force.m_nodeId      = 2;
            force.m_load[0]     = 0.0;
            force.m_load[1]     = 1000;
            force.m_load[2]     = 0.0;
            force.m_factor      = 0.29;
            force.m_sId         = 1;
            DB_SERVICEFACTORY->get<IMOMENTService> ()->Add (force);
        }

        {
            Subcase subcase;
            // subCase.m_id   = 1;
            // subCase.m_spc  = 1;
            // subCase.m_load = 1;
            // DB_SERVICEFACTORY->get<ISubcaseService> ()->Add (subCase);
            subcase.AddParameter ({ "SUBCASE", "1" });
            subcase.AddParameter ({ "SOL", "101" });
            subcase.AddParameter ({ "SPC", "1" });
            subcase.AddParameter ({ "LOAD", "1" });
            DB_SERVICEFACTORY->get<ISubcaseService> ()->Initial (subcase.Dump ());
        }
    }

    DBServiceFactorySP GetModel ()
    {
        return DB_SERVICEFACTORY;
    }
};

// simply supported beam
class OneBeamSimplySupported
{
  public:
    OneBeamSimplySupported ()
    {
        DB_SERVICEFACTORY->ClearDatabase ();
        inputOneBeamMesh (DB_SERVICEFACTORY);
        SG::DataStructure::FEM::SPCData spc;
        spc.m_sId = 1;
        // 约束1号节点线自由度
        spc.m_g = 1;
        spc.m_c = 123;
        DB_SERVICEFACTORY->get<ISPCService> ()->Add (spc);

        // 约束2号节点线自由度
        spc.m_g = 2;
        DB_SERVICEFACTORY->get<ISPCService> ()->Add (spc);
    }

    DBServiceFactorySP GetModel () const
    {
        return DB_SERVICEFACTORY;
    }
};